package com.example.utility.crypto.ecc;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author 季舟
 * @Date 2024-12-23 17:52
 */
public class ECCSignatureDemo {
    /**
     * 生成密钥对
     *
     * @param keySize 密钥长度
     * @return 密钥对
     */
    public static KeyPair generateKeyPair(int keySize) throws Exception {
        // 获取指定算法的密钥对生成器
        Security.addProvider(new BouncyCastleProvider());
        /**
         * 这段代码的功能是获取一个指定算法的密钥对生成器实例。具体来说：
         * 使用 KeyPairGenerator.getInstance("EC", "BC") 获取椭圆曲线（EC）算法的密钥对生成器。
         * 指定使用 BouncyCastle 提供者（"BC"）来生成密钥对。
         */
        final KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "BC");
        // 初始化密钥对生成器（指定密钥长度, 使用默认的安全随机数源）
        generator.initialize(keySize);
        // 随机生成一对密钥（包含公钥和私钥）
        return generator.generateKeyPair();
    }

    /**
     * 私钥签名
     *
     * @param privateKeyBytes 私钥
     * @param plain 原文
     * @return 签名
     */
    public static byte[] signature(byte[] privateKeyBytes, byte[] plain) throws Exception {
        // 创建EC算法的KeyFactory对象，使用BC（Bouncy Castle）提供者
        final KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");

        // 创建PKCS#8编码的私钥规范
        final PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);

        // 根据私钥规范生成PrivateKey对象
        final PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

        // 创建SHA256withECDSA算法的Signature对象
        final Signature signature = Signature.getInstance("SHA256withECDSA");

        // 初始化签名操作，使用生成的PrivateKey对象
        signature.initSign(privateKey);

        // 更新签名操作的数据，即原文
        signature.update(plain);

        // 执行签名操作并返回签名结果
        return signature.sign();
    }

    /**
     * 公钥验签
     *
     * @param publicKeyBytes 公钥
     * @param plain 原文
     * @param sign 签名
     */
    public static boolean verify(byte[] publicKeyBytes, byte[] plain, byte[] sign) throws Exception {
        // 创建KeyFactory对象，用于生成公钥
        final KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
        // 创建X509EncodedKeySpec对象，用于加载公钥字节数组
        final X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        // 生成公钥对象
        final PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
        // 创建Signature对象，用于进行签名验证
        final Signature signature = Signature.getInstance("SHA256withECDSA");
        // 初始化签名验证器，使用公钥
        signature.initVerify(publicKey);
        // 更新签名验证器，加载原文
        signature.update(plain);
        // 执行签名验证，返回验证结果
        return signature.verify(sign);
    }

    public static void main(String[] args) throws Exception{
        // 生成RSA密钥对
        final KeyPair keyPair = generateKeyPair(256);
        // 输出公钥和私钥，以便查看
        System.out.println("公钥:"+ Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()));
        System.out.println("私钥:"+Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()));
        // 定义待签名的原文字符串
        final String plain = "Hello, World!";
        System.out.println("原文：" + plain);
        // 使用私钥对原文进行签名
        final byte[] signature = signature(keyPair.getPrivate().getEncoded(), plain.getBytes());
        System.out.println("签名：" + Base64.getEncoder().encodeToString(signature));
        // 使用公钥对原文和签名进行验证
        final boolean result = verify(keyPair.getPublic().getEncoded(), plain.getBytes(), signature);
        System.out.println("验签结果：" + result);
    }
}
